package com.ithuameng.admin.job;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

import com.ithuameng.admin.app.system.model.SysJobLog;
import com.ithuameng.admin.app.system.service.ISysJobLogService;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;

/**
 * 模板设计模式: 将公共行为固定，动态算法抽象给子类实现，每个定时任务不一样
 *
 * @author ithuameng
 */
@Slf4j
@Setter
public abstract class AdminJob implements Job {

    private static ThreadLocal<LocalDateTime> threadLocal = new ThreadLocal<>();

    private String id;

    private String name;

    @Resource
    private ISysJobLogService sysJobLogService;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            before(context);
            doExecute(context);
            after(context, null);
        } catch (Exception e) {
            log.error("任务执行异常  - ：", e);
            after(context, e);
        }
    }

    /**
     * Job执行方法（在具体类中实现）
     *
     * @param context 工作执行上下文对象
     */
    public abstract void doExecute(JobExecutionContext context);

    /**
     * 执行前
     *
     * @param context 工作执行上下文对象
     */
    protected void before(JobExecutionContext context) {
        threadLocal.set(LocalDateTime.now());
    }

    /**
     * 执行后
     *
     * @param context   工作执行上下文对象
     * @param exception ignore
     */
    protected void after(JobExecutionContext context, Exception exception) {
        LocalDateTime endTime = LocalDateTime.now();
        LocalDateTime startTime = threadLocal.get();
        threadLocal.remove();

        JobDataMap jobDataMap = context.getMergedJobDataMap();
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.putAll(jobDataMap.getWrappedMap());
        // 删除id和name
        paramMap.remove("id");
        paramMap.remove("name");
        String parameter = paramMap.entrySet().stream().map(Object::toString).collect(Collectors.joining(","));
        final SysJobLog sysJobLog = new SysJobLog(id, name, parameter, startTime, endTime);
        if (exception != null) {
            sysJobLog.setStatus("F");
            sysJobLog.setExceptionMessage(exception.getMessage());
        } else {
            sysJobLog.setStatus("S");
        }
        sysJobLogService.save(sysJobLog);
    }

}
